libxenlight: implement support for pv guests
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 23 Nov 2009 06:54:03 +0000 (06:54 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 23 Nov 2009 06:54:03 +0000 (06:54 +0000)
This patch makes pv guest work correctly with libxenlight.  It also
implements support for vfb and vkbd, starting qemu in xenpv mode. Both
xenconsole and qemu are supported as console backends.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/libxl_device.c
tools/libxl/libxl_dom.c
tools/libxl/libxl_internal.h
tools/libxl/xl.c

index 45766fb3b2d9d399c7e97d6a8e6db3d9eb911236..1fd76690939385edbd4d85a1bb7a19ac25e72637 100644 (file)
@@ -23,6 +23,8 @@
 #include <sys/select.h>
 #include <signal.h>
 #include <unistd.h> /* for write, unlink and close */
+#include <stdint.h>
+#include <inttypes.h>
 #include "libxl.h"
 #include "libxl_utils.h"
 #include "libxl_internal.h"
@@ -156,7 +158,6 @@ retry_transaction:
 
     xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
     xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, strlen(info->name));
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/image/ostype", vm_path), "hvm", strlen("hvm"));
 
     libxl_xs_writev(ctx, t, dom_path, info->xsdata);
     libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), info->platformdata);
@@ -169,24 +170,33 @@ retry_transaction:
     return 0;
 }
 
-int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid)
+libxl_domain_build_state *libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid)
 {
-    libxl_domain_build_state state;
+    libxl_domain_build_state *state = (libxl_domain_build_state *) libxl_calloc(ctx, 1, sizeof(libxl_domain_build_state));
     char **vments = NULL, **localents = NULL;
 
-    memset(&state, '\0', sizeof(state));
-
-    build_pre(ctx, domid, info, &state);
+    build_pre(ctx, domid, info, state);
     if (info->hvm) {
-        build_hvm(ctx, domid, info, &state);
-        vments = libxl_calloc(ctx, 4, sizeof(char *));
+        build_hvm(ctx, domid, info, state);
+        vments = libxl_calloc(ctx, 5, sizeof(char *));
         vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
         vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "");
+        vments[2] = libxl_sprintf(ctx, "image/ostype");
+        vments[3] = libxl_sprintf(ctx, "hvm");
     } else {
-        build_pv(ctx, domid, info, &state);
+        build_pv(ctx, domid, info, state);
+        vments = libxl_calloc(ctx, 9, sizeof(char *));
+        vments[0] = libxl_sprintf(ctx, "image/ostype");
+        vments[1] = libxl_sprintf(ctx, "linux");
+        vments[2] = libxl_sprintf(ctx, "image/kernel");
+        vments[3] = libxl_sprintf(ctx, info->kernel);
+        vments[4] = libxl_sprintf(ctx, "image/ramdisk");
+        vments[5] = libxl_sprintf(ctx, info->u.pv.ramdisk);
+        vments[6] = libxl_sprintf(ctx, "image/cmdline");
+        vments[7] = libxl_sprintf(ctx, info->u.pv.cmdline);
     }
-    build_post(ctx, domid, info, &state, vments, localents);
-    return 0;
+    build_post(ctx, domid, info, state, vments, localents);
+    return state;
 }
 
 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
@@ -414,13 +424,6 @@ static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
         flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-domain-name"));
         flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->dom_name));
     }
-    if (info->videoram) {
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-videoram"));
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram));
-    }
-    if (info->stdvga) {
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-std-vga"));
-    }
     if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
         flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vnc"));
         if (info->vncdisplay) {
@@ -459,38 +462,47 @@ static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
         flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-serial"));
         flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->serial));
     }
-    if (info->boot) {
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-boot"));
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->boot));
-    }
-    if (info->usb) {
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usb"));
-        if (info->usbdevice) {
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usbdevice"));
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->usbdevice));
+    if (info->type == XENFV) {
+        if (info->videoram) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-videoram"));
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram));
         }
-    }
-    if (info->apic) {
-        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-acpi"));
-    }
-    if (info->extra) {
-        int i = 0;
-        while (info->extra[i] != NULL) {
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->extra[i]));
+        if (info->stdvga) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-std-vga"));
         }
-    }
-    for (i = 0; i < num_vifs; i++) {
-        if (vifs[i].nictype == NICTYPE_IOEMU) {
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s",
-                                                        vifs[i].devid, vifs[i].smac, vifs[i].model));
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
-            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s",
-                                                        vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
+
+        if (info->boot) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-boot"));
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->boot));
+        }
+        if (info->usb) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usb"));
+            if (info->usbdevice) {
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usbdevice"));
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->usbdevice));
+            }
+        }
+        if (info->apic) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-acpi"));
+        }
+        for (i = 0; i < num_vifs; i++) {
+            if (vifs[i].nictype == NICTYPE_IOEMU) {
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s",
+                            vifs[i].devid, vifs[i].smac, vifs[i].model));
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s",
+                            vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
+            }
         }
     }
+    for (i = 0; info->extra && info->extra[i] != NULL; i++)
+        flexarray_set(dm_args, num++, info->extra[i]);
     flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-M"));
-    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenfv"));
+    if (info->type == XENPV)
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenpv"));
+    else
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenfv"));
     flexarray_set(dm_args, num++, NULL);
 
     return (char **) flexarray_contents(dm_args);
@@ -579,7 +591,7 @@ int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_di
         case PHYSTYPE_PHY: {
             int major, minor;
 
-            device_disk_major_minor(disk->virtpath, &major, &minor);
+            device_physdisk_major_minor(disk->physpath, &major, &minor);
             flexarray_set(back, boffset++, libxl_sprintf(ctx, "physical-device"));
             flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
 
@@ -604,6 +616,8 @@ int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_di
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "removable"));
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", (disk->unpluggable) ? 1 : 0));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "bootable"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
     flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev"));
@@ -716,9 +730,125 @@ int libxl_device_nic_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
 }
 
 /******************************************************************************/
-int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid)
+int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
 {
-    return ERROR_NI;
+    flexarray_t *front;
+    flexarray_t *back;
+    unsigned int boffset = 0;
+    unsigned int foffset = 0;
+    libxl_device device;
+
+    if (console->build_state) {
+        xs_transaction_t t;
+        char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *));
+        ents[0] = libxl_sprintf(ctx, "console/port");
+        ents[1] = libxl_sprintf(ctx, "%"PRIu32, console->build_state->console_port);
+        ents[2] = libxl_sprintf(ctx, "console/ring-ref");
+        ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn);
+        ents[4] = libxl_sprintf(ctx, "console/limit");
+        ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT);
+        ents[6] = libxl_sprintf(ctx, "console/type");
+        if (console->constype == CONSTYPE_XENCONSOLED)
+            ents[7] = "xenconsoled";
+        else
+            ents[7] = "ioemu";
+retry_transaction:
+        t = xs_transaction_start(ctx->xsh);
+        libxl_xs_writev(ctx, t, xs_get_domain_path(ctx->xsh, console->domid), ents);
+        if (!xs_transaction_end(ctx->xsh, t, 0))
+            if (errno == EAGAIN)
+                goto retry_transaction;
+    }
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    device.backend_devid = console->devid;
+    device.backend_domid = console->backend_domid;
+    device.backend_kind = DEVICE_CONSOLE;
+    device.devid = console->devid;
+    device.domid = console->domid;
+    device.kind = DEVICE_CONSOLE;
+
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "protocol"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, LIBXL_XENCONSOLE_PROTOCOL));
+
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", console->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "limit"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, LIBXL_XENCONSOLE_PROTOCOL));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "type"));
+    if (console->constype == CONSTYPE_XENCONSOLED)
+        flexarray_set(front, foffset++, libxl_sprintf(ctx, "xenconsoled"));
+    else
+        flexarray_set(front, foffset++, libxl_sprintf(ctx, "ioemu"));
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+
+
+    return 0;
+}
+
+/******************************************************************************/
+int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
+{
+    flexarray_t *front;
+    flexarray_t *back;
+    unsigned int boffset = 0;
+    unsigned int foffset = 0;
+    libxl_device device;
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    device.backend_devid = vkb->devid;
+    device.backend_domid = vkb->backend_domid;
+    device.backend_kind = DEVICE_VKBD;
+    device.devid = vkb->devid;
+    device.domid = vkb->domid;
+    device.kind = DEVICE_VKBD;
+
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
+
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vkb->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+
+    return 0;
 }
 
 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
@@ -732,9 +862,119 @@ int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
 }
 
 /******************************************************************************/
-int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid)
+static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
+                                       libxl_device_vfb *vfb,
+                                       int num_console,
+                                       libxl_device_console *console,
+                                       libxl_device_model_info *info) {
+    int i = 0, j = 0, num = 0;
+    memset(info, 0x00, sizeof(libxl_device_model_info));
+
+    info->vnc = vfb->vnc;
+    if (vfb->vnclisten)
+        info->vnclisten = libxl_sprintf(ctx, "%s", vfb->vnclisten);
+    info->vncdisplay = vfb->vncdisplay;
+    info->vncunused = vfb->vncunused;
+    if (vfb->keymap)
+        info->keymap = libxl_sprintf(ctx, "%s", vfb->keymap);
+    info->sdl = vfb->sdl;
+    info->opengl = vfb->opengl;
+    for (i = 0; i < num_console; i++) {
+        if (console->constype == CONSTYPE_IOEMU)
+            num++;
+    }
+    if (num > 0) {
+        info->serial = "pty";
+        num--;
+    }
+    if (num > 0) {
+        info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *));
+        for (j = 0; j < num * 2; j = j + 2) {
+            info->extra[j] = "-serial";
+            info->extra[j + 1] = "pty";
+        }
+        info->extra[j] = NULL;
+    }
+    info->domid = vfb->domid;
+    info->dom_name = libxl_domid_to_name(ctx, vfb->domid);
+    info->device_model = "/usr/lib/xen/bin/qemu-dm";
+    info->type = XENPV;
+    return 0;
+}
+
+int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
+                            int num_console, libxl_device_console *console)
 {
-    return ERROR_NI;
+    libxl_device_model_info info;
+
+    libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
+    libxl_create_device_model(ctx, &info, NULL, 0);
+    return 0;
+}
+
+int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
+{
+    flexarray_t *front;
+    flexarray_t *back;
+    unsigned int boffset = 0;
+    unsigned int foffset = 0;
+    libxl_device device;
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    device.backend_devid = vfb->devid;
+    device.backend_domid = vfb->backend_domid;
+    device.backend_kind = DEVICE_VFB;
+    device.devid = vfb->devid;
+    device.domid = vfb->domid;
+    device.kind = DEVICE_VFB;
+
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "vnc"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "vnclisten"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", vfb->vnclisten));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "vncdisplay"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "vncunused"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "sdl"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "opengl"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl));
+    if (vfb->xauthority) {
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "xauthority"));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", vfb->xauthority));
+    }
+    if (vfb->display) {
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "display"));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", vfb->display));
+    }
+
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vfb->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+    flexarray_free(front);
+    flexarray_free(back);
+
+    return 0;
 }
 
 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
index 0241a0ea0b6eccc7efc374ce65a6fb2cf0f6871c..0c6f168feebf025a4424e59626c06998463d0e89 100644 (file)
@@ -76,19 +76,28 @@ typedef struct {
         struct {
             const char *cmdline;
             const char *ramdisk;
+            const char *features;
         } pv;
     } u;
 } libxl_domain_build_info;
 
+typedef struct libxl_domain_build_state_ libxl_domain_build_state;
+
 typedef struct {
     int flags;
     int (*suspend_callback)(void *, int);
 } libxl_domain_suspend_info;
 
+typedef enum {
+    XENFV,
+    XENPV,
+} libxl_qemu_machine_type;
+
 typedef struct {
     int domid;
     char *dom_name;
     char *device_model;
+    libxl_qemu_machine_type type;
     int videoram; /* size of the videoram in MB */
     bool stdvga; /* stdvga enabled or disabled */
     bool vnc; /* vnc enabled or disabled */
@@ -108,6 +117,40 @@ typedef struct {
     /* Network is missing */
 } libxl_device_model_info;
 
+typedef struct {
+    uint32_t backend_domid;
+    uint32_t domid;
+    int devid;
+    bool vnc; /* vnc enabled or disabled */
+    char *vnclisten; /* address:port that should be listened on for the VNC server if vnc is set */
+    int vncdisplay; /* set VNC display number */
+    bool vncunused; /* try to find an unused port for the VNC server */
+    char *keymap; /* set keyboard layout, default is en-us keyboard */
+    bool sdl; /* sdl enabled or disabled */
+    bool opengl; /* opengl enabled or disabled (if enabled requires sdl enabled) */
+    char *display;
+    char *xauthority;
+} libxl_device_vfb;
+
+typedef struct {
+    uint32_t backend_domid;
+    uint32_t domid;
+    int devid;
+} libxl_device_vkb;
+
+typedef enum {
+    CONSTYPE_XENCONSOLED,
+    CONSTYPE_IOEMU,
+} libxl_console_constype;
+
+typedef struct {
+    uint32_t backend_domid;
+    uint32_t domid;
+    int devid;
+    libxl_console_constype constype;
+    libxl_domain_build_state *build_state;
+} libxl_device_console;
+
 typedef enum {
     PHYSTYPE_QCOW,
     PHYSTYPE_QCOW2,
@@ -179,7 +222,7 @@ int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, vo
 
 /* domain related functions */
 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info, uint32_t *domid);
-int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid);
+libxl_domain_build_state *libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid);
 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
                           uint32_t domid, int fd);
 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info,
@@ -196,6 +239,8 @@ xc_dominfo_t * libxl_domain_infolist(struct libxl_ctx *ctx, int *nb_domain);
 int libxl_create_device_model(struct libxl_ctx *ctx,
                               libxl_device_model_info *info,
                               libxl_device_nic *vifs, int num_vifs);
+int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
+                            int num_console, libxl_device_console *console);
 
 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk);
 int libxl_device_disk_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
@@ -205,11 +250,13 @@ int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic
 int libxl_device_nic_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 int libxl_device_nic_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 
-int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console);
+
+int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb);
 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 
-int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb);
 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 
index 1355314a964ac32c6eea3723199bb798d839726b..eee0a40e0d3dbfbe8b9c94f2dda0d4d3efecd478 100644 (file)
@@ -19,6 +19,9 @@
 #include "libxl.h"
 #include "libxl_internal.h"
 #include <sys/time.h> /* for struct timeval */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 char *string_of_kinds[] = {
     [DEVICE_VIF] = "vif",
@@ -27,6 +30,7 @@ char *string_of_kinds[] = {
     [DEVICE_PCI] = "pci",
     [DEVICE_VFB] = "vfb",
     [DEVICE_VKBD] = "vkbd",
+    [DEVICE_CONSOLE] = "console",
 };
 
 int libxl_device_generic_add(struct libxl_ctx *ctx, libxl_device *device,
@@ -118,7 +122,17 @@ char *device_disk_backend_type_of_phystype(libxl_disk_phystype phystype)
     }
 }
 
-int device_disk_major_minor(char *virtpath, int *major, int *minor)
+int device_physdisk_major_minor(char *physpath, int *major, int *minor)
+{
+    struct stat buf;
+    if (stat(physpath, &buf) < 0)
+        return -1;
+    *major = major(buf.st_rdev);
+    *minor = minor(buf.st_rdev);
+    return 0;
+}
+
+int device_virtdisk_major_minor(char *virtpath, int *major, int *minor)
 {
     if (strstr(virtpath, "sd") == virtpath) {
         return -1;
@@ -146,9 +160,14 @@ int device_disk_dev_number(char *virtpath)
     int majors_table[] = { 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 };
     int major, minor;
 
-    if (device_disk_major_minor(virtpath, &major, &minor))
-        return -1;
-    return majors_table[major / 2] * 256 + (64 * (major % 2)) + minor;
+    if (strstr(virtpath, "hd") == virtpath) {
+        if (device_virtdisk_major_minor(virtpath, &major, &minor))
+            return -1;
+        return majors_table[major / 2] * 256 + (64 * (major % 2)) + minor;
+    } else if (strstr(virtpath, "xvd") == virtpath) {
+        return (202 << 8) + ((virtpath[3] - 'a') << 4) + (virtpath[4] ? (virtpath[4] - '0') : 0);
+    }
+    return -1;
 }
 
 int libxl_device_destroy(struct libxl_ctx *ctx, char *be_path, int force)
index 92e13242f274c16364bead83429d490c6bf7dc34..a98daee19be60e5bfb16901564794540db305c30 100644 (file)
 
 #include "libxl.h"
 #include "libxl_internal.h"
+#include <stdio.h>
 #include <inttypes.h>
 #include <xenguest.h>
+#include <xenctrl.h>
+#include <xc_dom.h>
 #include <string.h>
 #include <sys/time.h> /* for struct timeval */
 #include <unistd.h> /* for sleep(2) */
@@ -37,7 +40,6 @@ int is_hvm(struct libxl_ctx *ctx, uint32_t domid)
 int build_pre(struct libxl_ctx *ctx, uint32_t domid,
               libxl_domain_build_info *info, libxl_domain_build_state *state)
 {
-    unsigned long shadow;
     if (info->timer_mode != -1)
         xc_set_hvm_param(ctx->xch, domid, HVM_PARAM_TIMER_MODE,
                 (unsigned long) info->timer_mode);
@@ -48,8 +50,12 @@ int build_pre(struct libxl_ctx *ctx, uint32_t domid,
     xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus);
     xc_domain_setmaxmem(ctx->xch, domid, info->max_memkb + info->video_memkb);
     xc_domain_set_memmap_limit(ctx->xch, domid, info->max_memkb);
-    shadow = (info->shadow_memkb + 1023) / 1024;
-    xc_shadow_control(ctx->xch, domid, XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION, NULL, 0, &shadow, 0, NULL);
+
+    if (info->hvm) {
+        unsigned long shadow;
+        shadow = (info->shadow_memkb + 1023) / 1024;
+        xc_shadow_control(ctx->xch, domid, XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION, NULL, 0, &shadow, 0, NULL);
+    }
 
     state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, 0);
     state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, 0);
@@ -64,7 +70,7 @@ int build_post(struct libxl_ctx *ctx, uint32_t domid,
     xs_transaction_t t;
     char **ents;
 
-    ents = libxl_calloc(ctx, 6 * 2, sizeof(char *));
+    ents = libxl_calloc(ctx, 10 * 2, sizeof(char *));
     ents[0] = libxl_sprintf(ctx, "memory/static-max");
     ents[1] = libxl_sprintf(ctx, "%d", info->max_memkb);
     ents[2] = libxl_sprintf(ctx, "memory/target");
@@ -95,14 +101,25 @@ retry_transaction:
 int build_pv(struct libxl_ctx *ctx, uint32_t domid,
              libxl_domain_build_info *info, libxl_domain_build_state *state)
 {
-#if 0 /* unused variables */
-    int mem_target_kib = info->max_memkb;
-    char *domid_str = libxl_sprintf(ctx, "%d", domid);
-    char *memsize_str = libxl_sprintf(ctx, "%d", mem_target_kib / 1024);
-    char *store_port_str = libxl_sprintf(ctx, "%d", state->store_port);
-    char *console_port_str = libxl_sprintf(ctx, "%d", state->console_port);
-#endif
-    return ERROR_NI;
+    struct xc_dom_image *dom;
+    int ret;
+    int flags = 0;
+
+    dom = xc_dom_allocate(info->u.pv.cmdline, info->u.pv.features);
+    if (!dom) {
+        XL_LOG(ctx, XL_LOG_ERROR, "xc_dom_allocate failed: %d", dom);
+        return -1;
+    }
+    if ((ret = xc_dom_linux_build(ctx->xch, dom, domid, info->max_memkb / 1024,
+                                  info->kernel, info->u.pv.ramdisk, flags,
+                                  state->store_port, &state->store_mfn,
+                                  state->console_port, &state->console_mfn)) != 0) {
+        xc_dom_release(dom);
+        XL_LOG(ctx, XL_LOG_ERROR, "xc_dom_linux_build failed: %d", ret);
+        return -2;
+    }
+    xc_dom_release(dom);
+    return 0;
 }
 
 int build_hvm(struct libxl_ctx *ctx, uint32_t domid,
index 4bb713fc818807b2f9f88dfee5d1214682a1a78c..d6835be53ef8bb02edd8fe51fe74dafec9aae771 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 #ifndef LIBXL_INTERNAL_H
-# define LIBXL_INTERNAL_H
+#define LIBXL_INTERNAL_H
 
 #include <stdint.h>
 #include <stdarg.h>
@@ -28,6 +28,8 @@
 #include "libxl_utils.h"
 
 #define LIBXL_DESTROY_TIMEOUT 10
+#define LIBXL_XENCONSOLE_LIMIT 1048576
+#define LIBXL_XENCONSOLE_PROTOCOL "vt100"
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
 
 void xl_log(struct libxl_ctx *ctx, int loglevel, const char *file, int line, const char *func, char *fmt, ...);
 
-typedef struct {
+struct libxl_domain_build_state_ {
     uint32_t store_port;
     unsigned long store_mfn;
     uint32_t console_port;
     unsigned long console_mfn;
-} libxl_domain_build_state;
+};
 
 typedef enum {
     DEVICE_VIF,
@@ -61,6 +63,7 @@ typedef enum {
     DEVICE_PCI,
     DEVICE_VFB,
     DEVICE_VKBD,
+    DEVICE_CONSOLE,
 } libxl_device_kinds;
 
 typedef struct {
@@ -119,7 +122,8 @@ int core_suspend(struct libxl_ctx *ctx, uint32_t domid, int fd, int hvm, int liv
 char *device_disk_backend_type_of_phystype(libxl_disk_phystype phystype);
 char *device_disk_string_of_phystype(libxl_disk_phystype phystype);
 
-int device_disk_major_minor(char *virtpath, int *major, int *minor);
+int device_physdisk_major_minor(char *physpath, int *major, int *minor);
+int device_virtdisk_major_minor(char *virtpath, int *major, int *minor);
 int device_disk_dev_number(char *virtpath);
 
 int libxl_device_generic_add(struct libxl_ctx *ctx, libxl_device *device,
index 4395268b00088c4c361847cb105a47bf062a0f84..3b735ec78a588a9ee41e61266970a52a6ca28e11 100644 (file)
@@ -42,10 +42,14 @@ static void printf_info(libxl_domain_create_info *c_info,
                         int num_vifs,
                         libxl_device_pci *pcidevs,
                         int num_pcidevs,
+                        libxl_device_vfb *vfbs,
+                        int num_vfbs,
+                        libxl_device_vkb *vkb,
+                        int num_vkbs,
                         libxl_device_model_info *dm_info)
 {
     int i;
-    char uuid_str[18];
+    char uuid_str[37];
     printf("*** domain_create_info ***\n");
     printf("hvm: %d\n", c_info->hvm);
     printf("hap: %d\n", c_info->hap);
@@ -69,12 +73,12 @@ static void printf_info(libxl_domain_create_info *c_info,
     printf("vpt_align: %d\n", b_info->vpt_align);
     printf("max_vcpus: %d\n", b_info->max_vcpus);
     printf("max_memkb: %d\n", b_info->max_memkb);
-    printf("video_memkb: %d\n", b_info->video_memkb);
-    printf("shadow_memkb: %d\n", b_info->shadow_memkb);
     printf("kernel: %s\n", b_info->kernel);
     printf("hvm: %d\n", b_info->hvm);
 
-    if (b_info->hvm) {
+    if (c_info->hvm) {
+        printf("video_memkb: %d\n", b_info->video_memkb);
+        printf("shadow_memkb: %d\n", b_info->shadow_memkb);
         printf("    pae: %d\n", b_info->u.hvm.pae);
         printf("    apic: %d\n", b_info->u.hvm.apic);
         printf("    acpi: %d\n", b_info->u.hvm.acpi);
@@ -114,25 +118,43 @@ static void printf_info(libxl_domain_create_info *c_info,
         printf("opts msitranslate %d power_mgmt %d\n", pcidevs[i].msitranslate, pcidevs[i].power_mgmt);
     }
 
-    printf("\n\n\n*** device_model_info ***\n");
-    printf("domid: %d\n", dm_info->domid);
-    printf("dom_name: %s\n", dm_info->dom_name);
-    printf("device_model: %s\n", dm_info->device_model);
-    printf("videoram: %d\n", dm_info->videoram);
-    printf("stdvga: %d\n", dm_info->stdvga);
-    printf("vnc: %d\n", dm_info->vnc);
-    printf("vnclisten: %s\n", dm_info->vnclisten);
-    printf("vncdisplay: %d\n", dm_info->vncdisplay);
-    printf("vncunused: %d\n", dm_info->vncunused);
-    printf("keymap: %s\n", dm_info->keymap);
-    printf("sdl: %d\n", dm_info->sdl);
-    printf("opengl: %d\n", dm_info->opengl);
-    printf("nographic: %d\n", dm_info->nographic);
-    printf("serial: %s\n", dm_info->serial);
-    printf("boot: %s\n", dm_info->boot);
-    printf("usb: %d\n", dm_info->usb);
-    printf("usbdevice: %s\n", dm_info->usbdevice);
-    printf("apic: %d\n", dm_info->apic);
+    for (i = 0; i < num_vfbs; i++) {
+        printf("\n\n\n*** vfbs_info: %d ***\n", i);
+        printf("backend_domid %d\n", vfbs[i].backend_domid);
+        printf("domid %d\n", vfbs[i].domid);
+        printf("devid %d\n", vfbs[i].devid);
+        printf("vnc: %d\n", vfbs[i].vnc);
+        printf("vnclisten: %s\n", vfbs[i].vnclisten);
+        printf("vncdisplay: %d\n", vfbs[i].vncdisplay);
+        printf("vncunused: %d\n", vfbs[i].vncunused);
+        printf("keymap: %s\n", vfbs[i].keymap);
+        printf("sdl: %d\n", vfbs[i].sdl);
+        printf("opengl: %d\n", vfbs[i].opengl);
+        printf("display: %s\n", vfbs[i].display);
+        printf("xauthority: %s\n", vfbs[i].xauthority);
+    }
+
+    if (c_info->hvm) {
+        printf("\n\n\n*** device_model_info ***\n");
+        printf("domid: %d\n", dm_info->domid);
+        printf("dom_name: %s\n", dm_info->dom_name);
+        printf("device_model: %s\n", dm_info->device_model);
+        printf("videoram: %d\n", dm_info->videoram);
+        printf("stdvga: %d\n", dm_info->stdvga);
+        printf("vnc: %d\n", dm_info->vnc);
+        printf("vnclisten: %s\n", dm_info->vnclisten);
+        printf("vncdisplay: %d\n", dm_info->vncdisplay);
+        printf("vncunused: %d\n", dm_info->vncunused);
+        printf("keymap: %s\n", dm_info->keymap);
+        printf("sdl: %d\n", dm_info->sdl);
+        printf("opengl: %d\n", dm_info->opengl);
+        printf("nographic: %d\n", dm_info->nographic);
+        printf("serial: %s\n", dm_info->serial);
+        printf("boot: %s\n", dm_info->boot);
+        printf("usb: %d\n", dm_info->usb);
+        printf("usbdevice: %s\n", dm_info->usbdevice);
+        printf("apic: %d\n", dm_info->apic);
+    }
 }
 
 static char* compat_config_file(const char *filename)
@@ -208,10 +230,10 @@ void init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *
     b_info->vpt_align = -1;
     b_info->max_vcpus = 1;
     b_info->max_memkb = 32 * 1024;
-    b_info->shadow_memkb = libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
-    b_info->video_memkb = 8 * 1024;
-    b_info->kernel = "/usr/lib/xen/boot/hvmloader";
     if (c_info->hvm) {
+        b_info->shadow_memkb = libxl_get_required_shadow_memory(b_info->max_memkb, b_info->max_vcpus);
+        b_info->video_memkb = 8 * 1024;
+        b_info->kernel = "/usr/lib/xen/boot/hvmloader";
         b_info->hvm = 1;
         b_info->u.hvm.pae = 1;
         b_info->u.hvm.apic = 1;
@@ -282,11 +304,54 @@ void disk_info_domid_fixup(libxl_device_disk *disk_info, int domid)
     disk_info->domid = domid;
 }
 
+void vfb_info_domid_fixup(libxl_device_vfb *vfb, int domid)
+{
+    vfb->domid = domid;
+}
+
+void vkb_info_domid_fixup(libxl_device_vkb *vkb, int domid)
+{
+    vkb->domid = domid;
+}
+
+void console_info_domid_fixup(libxl_device_console *console, int domid)
+{
+    console->domid = domid;
+}
+
 void device_model_info_domid_fixup(libxl_device_model_info *dm_info, int domid)
 {
     dm_info->domid = domid;
 }
 
+void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
+{
+    memset(vfb, 0x00, sizeof(libxl_device_vfb));
+    vfb->devid = dev_num;
+    vfb->vnc = 1;
+    vfb->vnclisten = "127.0.0.1";
+    vfb->vncdisplay = 0;
+    vfb->vncunused = 1;
+    vfb->keymap = NULL;
+    vfb->sdl = 0;
+    vfb->opengl = 0;
+}
+
+void init_vkb_info(libxl_device_vkb *vkb, int dev_num)
+{
+    memset(vkb, 0x00, sizeof(libxl_device_vkb));
+    vkb->devid = dev_num;
+}
+
+void init_console_info(libxl_device_console *console, int dev_num, libxl_domain_build_state *state)
+{
+    memset(console, 0x00, sizeof(libxl_device_console));
+    console->devid = dev_num;
+    console->constype = CONSTYPE_XENCONSOLED;
+    if (state)
+        console->build_state = state;
+}
+
 static void parse_config_file(const char *filename,
                               libxl_domain_create_info *c_info,
                               libxl_domain_build_info *b_info,
@@ -296,13 +361,17 @@ static void parse_config_file(const char *filename,
                               int *num_vifs,
                               libxl_device_pci **pcidevs,
                               int *num_pcidevs,
+                              libxl_device_vfb **vfbs,
+                              int *num_vfbs,
+                              libxl_device_vkb **vkbs,
+                              int *num_vkbs,
                               libxl_device_model_info *dm_info)
 {
     const char *buf;
     xen_uuid_t uuid[16];
     long l;
     struct config_t config;
-    struct config_setting_t *vbds, *nics, *pcis;
+    struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
     int pci_power_mgmt = 0;
     int pci_msitranslate = 1;
 
@@ -367,10 +436,13 @@ static void parse_config_file(const char *filename,
         if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
             b_info->u.hvm.viridian = l;
     } else {
-        if (config_lookup_string (&config, "cmdline", &buf) == CONFIG_TRUE)
-            b_info->u.pv.cmdline = buf;
+        char *cmdline;
+        if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
+            asprintf(&cmdline, "root=%s", buf);
+            b_info->u.pv.cmdline = cmdline;
+        }
         if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
-            b_info->u.pv.ramdisk = buf;
+            b_info->u.pv.ramdisk = strdup(buf);
     }
 
     if ((vbds = config_lookup (&config, "disk")) != NULL) {
@@ -494,6 +566,56 @@ skip:
         }
     }
 
+    if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
+        *num_vfbs = 0;
+        *num_vkbs = 0;
+        *vfbs = NULL;
+        *vkbs = NULL;
+        while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
+            init_vfb_info((*vfbs) + (*num_vfbs), (*num_vfbs));
+
+            *vkbs = (libxl_device_vkb *) realloc(*vkbs, sizeof(libxl_device_vkb) * ((*num_vkbs) + 1));
+            init_vkb_info((*vkbs) + (*num_vkbs), (*num_vkbs));
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_vfb;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "vnc")) {
+                    (*vfbs)[*num_vfbs].vnc = atoi(p2 + 1);
+                } else if (!strcmp(p, "vnclisten")) {
+                    (*vfbs)[*num_vfbs].vnclisten = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncdisplay")) {
+                    (*vfbs)[*num_vfbs].vncdisplay = atoi(p2 + 1);
+                } else if (!strcmp(p, "vncunused")) {
+                    (*vfbs)[*num_vfbs].vncunused = atoi(p2 + 1);
+                } else if (!strcmp(p, "keymap")) {
+                    (*vfbs)[*num_vfbs].keymap = strdup(p2 + 1);
+                } else if (!strcmp(p, "sdl")) {
+                    (*vfbs)[*num_vfbs].sdl = atoi(p2 + 1);
+                } else if (!strcmp(p, "opengl")) {
+                    (*vfbs)[*num_vfbs].opengl = atoi(p2 + 1);
+                } else if (!strcmp(p, "display")) {
+                    (*vfbs)[*num_vfbs].display = strdup(p2 + 1);
+                } else if (!strcmp(p, "xauthority")) {
+                    (*vfbs)[*num_vfbs].xauthority = strdup(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_vfb:
+            free(buf2);
+            *num_vfbs = (*num_vfbs) + 1;
+            *num_vkbs = (*num_vkbs) + 1;
+        }
+    }
+
     if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
         pci_msitranslate = l;
 
@@ -536,38 +658,40 @@ skip_pci:
         }
     }
 
-    /* init dm from c and b */
-    init_dm_info(dm_info, c_info, b_info);
-
-    /* then process config related to dm */
-    if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
-        dm_info->device_model = strdup(buf);
-    if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
-        dm_info->stdvga = l;
-    if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
-        dm_info->vnc = l;
-    if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
-        dm_info->vnclisten = strdup(buf);
-    if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
-        dm_info->vncdisplay = l;
-    if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
-        dm_info->vncunused = l;
-    if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
-        dm_info->keymap = strdup(buf);
-    if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
-        dm_info->sdl = l;
-    if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
-        dm_info->opengl = l;
-    if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
-        dm_info->nographic = l;
-    if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
-        dm_info->serial = strdup(buf);
-    if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
-        dm_info->boot = strdup(buf);
-    if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
-        dm_info->usb = l;
-    if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
-        dm_info->usbdevice = strdup(buf);
+    if (c_info->hvm == 1) {
+        /* init dm from c and b */
+        init_dm_info(dm_info, c_info, b_info);
+
+        /* then process config related to dm */
+        if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
+            dm_info->device_model = strdup(buf);
+        if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
+            dm_info->stdvga = l;
+        if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
+            dm_info->vnc = l;
+        if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
+            dm_info->vnclisten = strdup(buf);
+        if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
+            dm_info->vncdisplay = l;
+        if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
+            dm_info->vncunused = l;
+        if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
+            dm_info->keymap = strdup(buf);
+        if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
+            dm_info->sdl = l;
+        if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
+            dm_info->opengl = l;
+        if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
+            dm_info->nographic = l;
+        if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
+            dm_info->serial = strdup(buf);
+        if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
+            dm_info->boot = strdup(buf);
+        if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
+            dm_info->usb = l;
+        if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
+            dm_info->usbdevice = strdup(buf);
+    }
 
     config_destroy(&config);
 }
@@ -578,24 +702,26 @@ static void create_domain(int debug, const char *filename)
     uint32_t domid;
     libxl_domain_create_info info1;
     libxl_domain_build_info info2;
+    libxl_domain_build_state *state;
     libxl_device_model_info dm_info;
     libxl_device_disk *disks = NULL;
     libxl_device_nic *vifs = NULL;
     libxl_device_pci *pcidevs = NULL;
-    int num_disks = 0, num_vifs = 0, num_pcidevs = 0;
+    libxl_device_vfb *vfbs = NULL;
+    libxl_device_vkb *vkbs = NULL;
+    libxl_device_console console;
+    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
     int i;
 
     printf("Parsing config file %s\n", filename);
-    parse_config_file(filename, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &dm_info);
+    parse_config_file(filename, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
     if (debug)
-        printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, &dm_info);
+        printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
 
     libxl_ctx_init(&ctx);
     libxl_ctx_set_log(&ctx, log_callback, NULL);
     libxl_domain_make(&ctx, &info1, &domid);
-    libxl_domain_build(&ctx, &info2, domid);
-
-    device_model_info_domid_fixup(&dm_info, domid);
+    state = libxl_domain_build(&ctx, &info2, domid);
 
     for (i = 0; i < num_disks; i++) {
         disk_info_domid_fixup(disks + i, domid);
@@ -605,7 +731,24 @@ static void create_domain(int debug, const char *filename)
         nic_info_domid_fixup(vifs + i, domid);
         libxl_device_nic_add(&ctx, domid, &vifs[i]);
     }
-    libxl_create_device_model(&ctx, &dm_info, vifs, num_vifs);
+    if (info1.hvm) {
+        device_model_info_domid_fixup(&dm_info, domid);
+        libxl_create_device_model(&ctx, &dm_info, vifs, num_vifs);
+    } else {
+        for (i = 0; i < num_vfbs; i++) {
+            vfb_info_domid_fixup(vfbs + i, domid);
+            libxl_device_vfb_add(&ctx, domid, &vfbs[i]);
+            vkb_info_domid_fixup(vkbs + i, domid);
+            libxl_device_vkb_add(&ctx, domid, &vkbs[i]);
+        }
+        init_console_info(&console, 0, state);
+        console_info_domid_fixup(&console, domid);
+        if (num_vfbs)
+            console.constype = CONSTYPE_IOEMU;
+        libxl_device_console_add(&ctx, domid, &console);
+        if (num_vfbs)
+            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console);
+    }
     for (i = 0; i < num_pcidevs; i++)
         libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
     libxl_domain_unpause(&ctx, domid);